using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Timing;
using Matrix.Configuration.Services;
using Matrix.Configuration.Events;

namespace Matrix.Application.Services
{
    /// <summary>
    /// 配置事件指标收集器实现
    /// 负责收集和报告事件相关的性能指标
    /// </summary>
    public class ConfigurationEventMetrics : IConfigurationEventMetrics, ITransientDependency
    {
        private readonly ILogger<ConfigurationEventMetrics> _logger;
        private readonly IClock _clock;
        private readonly ConcurrentDictionary<string, EventTypeMetrics> _eventTypeMetrics;
        private readonly ConcurrentDictionary<string, CacheMetrics> _cacheMetrics;
        private readonly ConcurrentDictionary<string, ValidationMetrics> _validationMetrics;

        private long _totalPublishedEvents;
        private long _totalProcessedEvents;
        private long _totalSuccessfulEvents;
        private long _totalFailedEvents;
        private long _totalRetryCount;
        private long _currentActiveEvents;
        private double _totalProcessingTimeMs;

        public ConfigurationEventMetrics(ILogger<ConfigurationEventMetrics> logger, IClock clock)
        {
            _logger = logger;
            _clock = clock;
            _eventTypeMetrics = new ConcurrentDictionary<string, EventTypeMetrics>();
            _cacheMetrics = new ConcurrentDictionary<string, CacheMetrics>();
            _validationMetrics = new ConcurrentDictionary<string, ValidationMetrics>();

            ResetMetrics();
        }

        public void RecordEventPublished(string eventType, ConfigurationImportanceLevel importance, bool isLocal)
        {
            try
            {
                System.Threading.Interlocked.Increment(ref _totalPublishedEvents);

                // 更新事件类型指标
                var metrics = _eventTypeMetrics.GetOrAdd(eventType, _ => new EventTypeMetrics
                {
                    EventType = eventType,
                    MinProcessingTimeMs = double.MaxValue
                });

                lock (metrics)
                {
                    metrics.PublishedCount++;
                    if (isLocal)
                    {
                        metrics.LocalEventCount++;
                    }
                    else
                    {
                        metrics.DistributedEventCount++;
                    }
                }

                // 更新重要性级别统计
                // 这里可以扩展添加按重要性级别的统计

                _logger.LogDebug("记录事件发布: EventType: {EventType}, Importance: {Importance}, IsLocal: {IsLocal}",
                    eventType, importance, isLocal);
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "记录事件发布指标失败: EventType: {EventType}", eventType);
            }
        }

        public void RecordEventProcessed(string eventType, bool success, TimeSpan duration, bool isLocal)
        {
            try
            {
                System.Threading.Interlocked.Increment(ref _totalProcessedEvents);
                var currentTime = _totalProcessingTimeMs + duration.TotalMilliseconds;
                System.Threading.Interlocked.Exchange(ref _totalProcessingTimeMs, currentTime);

                if (success)
                {
                    System.Threading.Interlocked.Increment(ref _totalSuccessfulEvents);
                }
                else
                {
                    System.Threading.Interlocked.Increment(ref _totalFailedEvents);
                }

                // 更新事件类型指标
                var metrics = _eventTypeMetrics.GetOrAdd(eventType, _ => new EventTypeMetrics
                {
                    EventType = eventType,
                    MinProcessingTimeMs = double.MaxValue
                });

                lock (metrics)
                {
                    metrics.ProcessedCount++;
                    if (success)
                    {
                        metrics.SuccessCount++;
                    }
                    else
                    {
                        metrics.FailureCount++;
                    }

                    var durationMs = duration.TotalMilliseconds;
                    metrics.AverageProcessingTimeMs =
                        (metrics.AverageProcessingTimeMs * (metrics.ProcessedCount - 1) + durationMs) / metrics.ProcessedCount;
                    metrics.MinProcessingTimeMs = Math.Min(metrics.MinProcessingTimeMs, durationMs);
                    metrics.MaxProcessingTimeMs = Math.Max(metrics.MaxProcessingTimeMs, durationMs);
                    metrics.LastProcessedTime = _clock.Now;

                    if (isLocal)
                    {
                        metrics.LocalEventCount++;
                    }
                    else
                    {
                        metrics.DistributedEventCount++;
                    }
                }

                _logger.LogDebug("记录事件处理: EventType: {EventType}, Success: {Success}, Duration: {Duration}ms, IsLocal: {IsLocal}",
                    eventType, success, duration.TotalMilliseconds, isLocal);
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "记录事件处理指标失败: EventType: {EventType}", eventType);
            }
        }

        public void RecordEventRetry(string eventType, int retryCount)
        {
            try
            {
                System.Threading.Interlocked.Add(ref _totalRetryCount, retryCount);

                // 更新事件类型指标
                var metrics = _eventTypeMetrics.GetOrAdd(eventType, _ => new EventTypeMetrics
                {
                    EventType = eventType
                });

                lock (metrics)
                {
                    metrics.RetryCount += retryCount;
                }

                _logger.LogDebug("记录事件重试: EventType: {EventType}, RetryCount: {RetryCount}",
                    eventType, retryCount);
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "记录事件重试指标失败: EventType: {EventType}", eventType);
            }
        }

        public void RecordEventFailure(string eventType, string errorType, bool isLocal)
        {
            try
            {
                // 失败指标在RecordEventProcessed中已经记录，这里可以记录错误类型统计
                _logger.LogDebug("记录事件失败: EventType: {EventType}, ErrorType: {ErrorType}, IsLocal: {IsLocal}",
                    eventType, errorType, isLocal);
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "记录事件失败指标失败: EventType: {EventType}, ErrorType: {ErrorType}",
                    eventType, errorType);
            }
        }

        public void RecordCacheHit(string cacheType, bool hit)
        {
            try
            {
                var metrics = _cacheMetrics.GetOrAdd(cacheType, _ => new CacheMetrics
                {
                    CacheType = cacheType
                });

                lock (metrics)
                {
                    metrics.TotalRequests++;
                    if (hit)
                    {
                        metrics.HitCount++;
                    }
                }

                _logger.LogDebug("记录缓存命中: CacheType: {CacheType}, Hit: {Hit}",
                    cacheType, hit);
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "记录缓存命中指标失败: CacheType: {CacheType}", cacheType);
            }
        }

        public void RecordConfigurationValidation(string validationType, bool success, TimeSpan duration)
        {
            try
            {
                var metrics = _validationMetrics.GetOrAdd(validationType, _ => new ValidationMetrics
                {
                    ValidationType = validationType,
                    MinProcessingTimeMs = double.MaxValue
                });

                lock (metrics)
                {
                    metrics.TotalValidations++;
                    if (success)
                    {
                        metrics.SuccessCount++;
                    }
                    else
                    {
                        metrics.FailureCount++;
                    }

                    var durationMs = duration.TotalMilliseconds;
                    metrics.AverageProcessingTimeMs =
                        (metrics.AverageProcessingTimeMs * (metrics.TotalValidations - 1) + durationMs) / metrics.TotalValidations;
                    metrics.MinProcessingTimeMs = Math.Min(metrics.MinProcessingTimeMs, durationMs);
                    metrics.MaxProcessingTimeMs = Math.Max(metrics.MaxProcessingTimeMs, durationMs);
                }

                _logger.LogDebug("记录配置验证: ValidationType: {ValidationType}, Success: {Success}, Duration: {Duration}ms",
                    validationType, success, duration.TotalMilliseconds);
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "记录配置验证指标失败: ValidationType: {ValidationType}", validationType);
            }
        }

        public void IncrementActiveEvents(string eventType, int count = 1)
        {
            try
            {
                System.Threading.Interlocked.Add(ref _currentActiveEvents, count);

                // 更新事件类型活跃计数
                var metrics = _eventTypeMetrics.GetOrAdd(eventType, _ => new EventTypeMetrics
                {
                    EventType = eventType
                });

                lock (metrics)
                {
                    metrics.CurrentActive += count;
                }

                _logger.LogDebug("增加活跃事件: EventType: {EventType}, Count: {Count}, TotalActive: {TotalActive}",
                    eventType, count, _currentActiveEvents);
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "增加活跃事件计数失败: EventType: {EventType}", eventType);
            }
        }

        public void DecrementActiveEvents(string eventType, int count = 1)
        {
            try
            {
                System.Threading.Interlocked.Add(ref _currentActiveEvents, -count);

                // 更新事件类型活跃计数
                var metrics = _eventTypeMetrics.GetOrAdd(eventType, _ => new EventTypeMetrics
                {
                    EventType = eventType
                });

                lock (metrics)
                {
                    metrics.CurrentActive = Math.Max(0, metrics.CurrentActive - count);
                }

                _logger.LogDebug("减少活跃事件: EventType: {EventType}, Count: {Count}, TotalActive: {TotalActive}",
                    eventType, count, _currentActiveEvents);
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "减少活跃事件计数失败: EventType: {EventType}", eventType);
            }
        }

        public async Task<EventMetricsSummary> GetMetricsSummaryAsync()
        {
            return await Task.FromResult(new EventMetricsSummary
            {
                TotalPublishedEvents = _totalPublishedEvents,
                TotalProcessedEvents = _totalProcessedEvents,
                TotalSuccessfulEvents = _totalSuccessfulEvents,
                TotalFailedEvents = _totalFailedEvents,
                TotalRetryCount = _totalRetryCount,
                AverageProcessingTimeMs = _totalProcessedEvents > 0 ? _totalProcessingTimeMs / _totalProcessedEvents : 0,
                CurrentActiveEvents = _currentActiveEvents,
                LocalEventCount = _eventTypeMetrics.Values.Sum(m => m.LocalEventCount),
                DistributedEventCount = _eventTypeMetrics.Values.Sum(m => m.DistributedEventCount),
                EventTypeMetrics = new Dictionary<string, EventTypeMetrics>(_eventTypeMetrics),
                CacheHitRates = _cacheMetrics.ToDictionary(
                    kvp => kvp.Key,
                    kvp => kvp.Value.TotalRequests > 0 ? (double)kvp.Value.HitCount / kvp.Value.TotalRequests : 0.0),
                LastUpdated = _clock.Now
            });
        }

        public async Task<EventTypeMetrics> GetEventTypeMetricsAsync(string eventType)
        {
            return await Task.FromResult(_eventTypeMetrics.TryGetValue(eventType, out var metrics)
                ? metrics
                : new EventTypeMetrics { EventType = eventType });
        }

        public void ResetMetrics()
        {
            try
            {
                System.Threading.Interlocked.Exchange(ref _totalPublishedEvents, 0);
                System.Threading.Interlocked.Exchange(ref _totalProcessedEvents, 0);
                System.Threading.Interlocked.Exchange(ref _totalSuccessfulEvents, 0);
                System.Threading.Interlocked.Exchange(ref _totalFailedEvents, 0);
                System.Threading.Interlocked.Exchange(ref _totalRetryCount, 0);
                System.Threading.Interlocked.Exchange(ref _currentActiveEvents, 0);
                System.Threading.Interlocked.Exchange(ref _totalProcessingTimeMs, 0);

                _eventTypeMetrics.Clear();
                _cacheMetrics.Clear();
                _validationMetrics.Clear();

                _logger.LogInformation("所有事件指标已重置");
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "重置事件指标失败");
            }
        }

        /// <summary>
        /// 缓存指标
        /// </summary>
        private class CacheMetrics
        {
            public string CacheType { get; set; } = string.Empty;
            public long TotalRequests { get; set; }
            public long HitCount { get; set; }
            public double HitRate => TotalRequests > 0 ? (double)HitCount / TotalRequests : 0.0;
        }

        /// <summary>
        /// 验证指标
        /// </summary>
        private class ValidationMetrics
        {
            public string ValidationType { get; set; } = string.Empty;
            public long TotalValidations { get; set; }
            public long SuccessCount { get; set; }
            public long FailureCount { get; set; }
            public double SuccessRate => TotalValidations > 0 ? (double)SuccessCount / TotalValidations : 0.0;
            public double AverageProcessingTimeMs { get; set; }
            public double MinProcessingTimeMs { get; set; } = double.MaxValue;
            public double MaxProcessingTimeMs { get; set; }
        }
    }
}